Модуль:Arguments
Этот модуль обеспечивает легкую обработку аргументов, передаваемых Scribunto из -- #применять. Он предназначен для использования другими модулями Lua, и не должно быть -- вызывается из #invoke напрямую. local libraryUtil = require('libraryUtil') local checkType = libraryUtil.checkType local arguments = {} -- Создание четырех различных функций tidyVal, так что нам не придется проверять -- варианты каждый раз, когда мы называем его. local function tidyValDefault(key, val) if type(val) 'string' then val = val:match('^%s*(.-)%s*$') if val '' then return nil else return val end else return val end end local function tidyValTrimOnly(key, val) if type(val) 'string' then return val:match('^%s*(.-)%s*$') else return val end end local function tidyValRemoveBlanksOnly(key, val) if type(val) 'string' then if val:find('%S') then return val else return nil end else return val end end local function tidyValNoChange(key, val) return val end function arguments.getArgs(frame, options) checkType('getArgs', 1, frame, 'table', true) checkType('getArgs', 2, options, 'table', true) frame = frame or {} options = options or {} -- -- Получить таблицы аргументов. Если нам был передан допустимый объект frame, получим -- аргументы кадр (fargs) и родительского фрейма аргументы (pargs), в зависимости от -- о наборе опций и доступности родительского фрейма. Если бы мы не были -- передан допустимый объект кадра, мы вызываемся из другого модуля Lua -- или из консоли отладки, поэтому предположим, что нам передали таблицу args -- непосредственно, и назначить его новой переменной (luaArgs). -- local fargs, pargs, luaArgs if type(frame.args) 'table' and type(frame.getParent) 'function' then if options.wrappers then -- -- Опция обертки делает модуль:аргументы искать аргументы в -- либо таблица аргументов фрейма, либо родительская таблица аргументов, но -- не оба. Это означает, что пользователи могут использовать синтаксис #вызов -- или шаблон оболочки без потери производительности -- ищет аргументы в обе рамы и родительского фрейма. -- Module:Arguments будет искать аргументы в Родительском фрейме -- если он находит заголовок родительского фрейма в options.обертка; -- в противном случае он будет искать аргументы в переданном объекте фрейма -- в getArgs. -- local parent = frame:getParent() if not parent then fargs = frame.args else local title = parent:getTitle():gsub('/sandbox$', '') local found = false if type(options.wrappers) 'table' then for _,v in pairs(options.wrappers) do if v title then found = true break end end elseif options.wrappers title then found = true end if found then pargs = parent.args else fargs = frame.args end end else -- опционы.обертка не установлена, поэтому проверьте другие параметры. if not options.parentOnly then fargs = frame.args end if not options.frameOnly then local parent = frame:getParent() pargs = parent and parent.args or nil end if options.parentFirst then fargs, pargs = pargs, fargs end end else luaArgs = frame end -- Установить порядок приоритета таблиц аргументов. Если переменные -- ноль, ничего не будет добавлено к столу, именно так мы избегаем столкновений -- между args рамки/родителя и args Lua. local argTables = {fargs} argTables+ 1 = pargs argTables+ 1 = luaArgs -- -- Создание функции tidyVal. Если оно было определено потребителем, то мы -- используйте это; если нет, мы выбираем одну из четырех функций в зависимости от -- варианты выбраны. Это делается для того, чтобы нам не пришлось вызывать таблицу параметров -- каждый раз, когда функция вызывается. -- local tidyVal = options.valueFunc if tidyVal then if type(tidyVal) ~= 'function' then error( "bad value assigned to option 'valueFunc'" .. '(function expected, got ' .. type(tidyVal) .. ')', 2 ) end elseif options.trim ~= false then if options.removeBlanks ~= false then tidyVal = tidyValDefault else tidyVal = tidyValTrimOnly end else if options.removeBlanks ~= false then tidyVal = tidyValRemoveBlanksOnly else tidyVal = tidyValNoChange end end -- -- Настройте таблицы args, metaArgs и nilArgs. аргументы будет один -- доступ из функций, и metaArgs будет содержать фактические аргументы. Ноль -- аргументы записываются в nilArgs, и метатабель соединяет их все -- вместе. -- local args, metaArgs, nilArgs, metatable = {}, {}, {}, {} setmetatable(args, metatable) local function mergeArgs(iterator, tables) -- -- Принимает несколько таблиц в качестве входных данных и объединяет их ключи и значения -- в одну таблицу с использованием указанного итератора. Если значение уже есть -- present не перезаписывается; таблицы, перечисленные ранее, имеют приоритет. -- Мы также записываем нулевые значения, но эти значения могут быть -- перезаписанный. -- for _, t in ipairs(tables) do for key, val in iterator(t) do if metaArgskey nil then local tidiedVal = tidyVal(key, val) if tidiedVal nil then nilArgskey = true else metaArgskey = tidiedVal end end end end end -- -- Определение поведения метатаблиц. Аргументы записываются в таблицу metaArgs, -- и извлекаются из таблиц аргументов только один раз. Получение аргументов -- из таблицы аргументов является наиболее ресурсоемким шагом в этом -- модуль, поэтому мы стараемся избегать, где это возможно. По этой причине, Ноль -- аргументы также memoized, в таблице nilArgs. Также мы ведем учет -- в metatable когда пары и ipairs были вызваны, поэтому мы не делаем -- запуск пар и ipairs на таблицах аргументов более одного раза. Мы также делаем -- не беги ipairs на fargs и pargs, если пар уже работать, как все -- аргументы уже будут скопированы. -- metatable.__index = function (t, key) -- -- Извлекает аргумент при индексировании таблицы args. Сначала проверим -- чтобы увидеть, если значение memoized, и если нет, то мы пытаемся извлечь его из -- таблицы аргументов. Когда мы проверяем memoization, нам нужно проверить -- metaArgs перед nilArgs, как может быть не-ноль в то же время. -- Если аргумент отсутствует в metaArgs, мы также проверяем -- пары еще не запущены. Если пары уже были запущены, мы возвращаем ноль. -- Это потому, что все аргументы будут уже скопированы в -- metaArgs по mergeArgs функции, т. е. какие-то другие аргументы -- должно быть ноль. -- local val = metaArgskey if val ~= nil then return val elseif metatable.donePairs or nilArgskey then return nil end for _, argTable in ipairs(argTables) do local argTableVal = tidyVal(key, argTablekey) if argTableVal nil then nilArgskey = true else metaArgskey = argTableVal return argTableVal end end return nil end metatable.__newindex = function (t, key, val) -- Эта функция вызывается, когда модуль пытается добавить новое значение в -- аргументы таблица, или пытается изменить существующее значение. if options.readOnly then error( 'could not write to argument table key "' .. tostring(key) .. '"; the table is read-only', 2 ) elseif options.noOverwrite and argskey ~= nil then error( 'could not write to argument table key "' .. tostring(key) .. '"; overwriting existing arguments is not permitted', 2 ) elseif val nil then -- -- Если аргумент должен быть перезаписан на ноль, нам нужно стереть -- значение в metaArgs, так что __индекс, __пар __ipairs делать -- не использовать предыдущее существующее значение, если оно есть; и нам также необходимо -- чтобы запомнить ноль в nilArgs, так что значение не выглядит - в таблицах аргумент, если она доступна. -- metaArgskey = nil nilArgskey = true else metaArgskey = val end end metatable.__pairs = function () -- Вызывается при запуске пар в таблице args. if not metatable.donePairs then mergeArgs(pairs, argTables) metatable.donePairs = true metatable.doneIpairs = true end return pairs(metaArgs) end metatable.__ipairs = function () -- Вызывается при запуске пар в таблице args. if not metatable.doneIpairs then mergeArgs(ipairs, argTables) metatable.doneIpairs = true end return ipairs(metaArgs) end return args end return arguments --Category:Модули Луа